/*
 * JniApplication.cpp
 *
 *  Created on: 2018年8月28日
 *      Author: zhengboyuan
 */

#include "JniApplication.h"
#include "TSingleton.h"
#include "CLog.h"



typedef comn::Singleton< JniApplication >		JniApplicationSingleton;


JniApplication& JniApplication::instance()
{
	return JniApplicationSingleton::instance();
}


JniApplication::JniApplication():
		m_jvm(),
		m_listener()
{
}

JniApplication::~JniApplication()
{
	close();
}

void JniApplication::init()
{
	av::MediaStorage::startup();

	CLog::setLogger(CLog::COUT);
}

void JniApplication::quit()
{
	av::MediaStorage::cleanup();
}

bool JniApplication::open(const char* dbpath)
{
	getStorage().setEventSink(this);

	return getStorage().open(dbpath);
}

void JniApplication::close()
{
	getStorage().close();
}

bool JniApplication::isOpen()
{
	return (getStorage().isOpen());
}

av::MediaStorage& JniApplication::getStorage()
{
	return av::MediaStorage::instance();
}

int JniApplication::openChannel(const char* device)
{
	if (device == NULL || strlen(device) == 0)
	{
		return -1;
	}

	av::MediaStorageChannelDeleter deleter(&getStorage());
	MediaStorageChannelPtr channel(getStorage().openChannel(device), deleter);
	return m_channels.put(channel);
}

void JniApplication::closeChannel(int handle)
{
	MediaStorageChannelPtr channel;
	m_channels.remove(handle, channel);
	if (!channel)
	{
		return;
	}

	channel->stopRecord();
}

MediaStorageChannelPtr JniApplication::getChannel(int handle)
{
	if (handle >= m_channels.capacity())
	{
		return MediaStorageChannelPtr();
	}

	return m_channels.getAt(handle);
}

void JniApplication::setJvm(JavaVM* jvm)
{
	m_jvm = jvm;
}

void JniApplication::onStorageEvent(const av::StorageEvent& event)
{
	CLog::info("JniApplication::onStorageEvent. type: %d\n", event.type);

	fireStorageEvent(event);
}

void JniApplication::setListener(JNIEnv * env, jobject jlistener)
{
	releaseListener(env);

	if (!jlistener)
	{
		return;
	}

	comn::AutoCritSec lock(m_cs);
	m_listener = env->NewGlobalRef(jlistener);
}

void JniApplication::releaseListener(JNIEnv * env)
{
	comn::AutoCritSec lock(m_cs);

	if (m_listener)
	{
		env->DeleteGlobalRef(m_listener);
		m_listener = NULL;
	}
}

void JniApplication::fireStorageEvent(const av::StorageEvent& event)
{
	if (!m_listener)
	{
		return;
	}

	JNIEnv* env = NULL;
	m_jvm->AttachCurrentThread(&env, NULL);

	{
		comn::AutoCritSec lock(m_cs);

		jclass cls = env->GetObjectClass(m_listener);
		jmethodID callback = env->GetMethodID(cls, "onStorageEvent", "(ILjava/lang/String;ILjava/lang/String;)V");
			//CLog::info("begin jni event sink. callback:%p", callback);
		if (callback)
		{
			jstring jdevice = env->NewStringUTF(event.device);
			jstring jfilepath = env->NewStringUTF(event.data.record.filepath);

			env->CallVoidMethod(m_listener, callback, event.type, jdevice, event.data.record.id, jfilepath);
		}
	}

	m_jvm->DetachCurrentThread();
}
